
#include <iostream>
#include <atomic>
#include <thread>
#include <cassert>


std::atomic<bool> g_bX{false}, g_bY{false};
std::atomic<int> g_iZ{0};


void app_write_x_then_y()
{
    g_bX.store(true, std::memory_order_relaxed);
    g_bY.store(true, std::memory_order_relaxed);
}

void app_read_x_then_y()
{
    while (!g_bY.load(std::memory_order_relaxed));

    if (g_bX.load(std::memory_order_relaxed))
    {
        g_iZ++;
    }
}


void app_write_x_then_y_fence()
{
    g_bX.store(true, std::memory_order_relaxed);

    // std::memory_order_release 该屏障之后的读写指令不会排到屏障之前
    std::atomic_thread_fence(std::memory_order_release);

    g_bY.store(true, std::memory_order_relaxed);
}

void app_read_x_then_y_fence()
{
    while (!g_bY.load(std::memory_order_relaxed));

    // std::memory_order_acquire 该屏障之前的读写指令不会排到屏障之后
    std::atomic_thread_fence(std::memory_order_acquire);

    if (g_bX.load(std::memory_order_relaxed))
    {
        g_iZ++;
    }
}

void test_only_atomic()
{
    std::thread t1(app_write_x_then_y);
    std::thread t2(app_read_x_then_y);

    t1.join();
    t2.join();

    assert(g_iZ.load() != 0);
}


void app_atomic_bool()
{
    std::atomic<bool> atmFlag(false);
    bool bExpected = false;

    // 原子操作引入了一种新的操作类型，“比较-交换”
    // 将原子变量的值和期望的值进行比较
    // 如果 原子变量的值和期望的值相等，原子变量存储提供的新值，并返回 true
    // 如果原子变量的当前值和期望值不相等，期望值被修改为原子变量的当前值，并返回false
    bool bRet = atmFlag.compare_exchange_strong(bExpected, true);
    printf("Return: %hhu\nExpected: %hhu\natmFlag: %hhu\n\n", bRet, bExpected, atmFlag.load());

    bExpected = false;
    bRet = atmFlag.compare_exchange_strong(bExpected, true);
    printf("Return: %hhu\nExpected: %hhu\natmFlag: %hhu\n", bRet, bExpected, atmFlag.load());
}   

int main(int argc, char** argv)
{
    test_only_atomic();

    app_atomic_bool();

    return 0;
}